/**************************************
 * This file contains the definitions *
 * for the Window Class.              *
 **************************************/

#include "Window.h"

namespace WindowsFramework
{
	//Callback Function Definition
	LRESULT CALLBACK WindowProcedure (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
	{
		switch (uMsg)
		{
			case WM_DESTROY:
				{
					PostQuitMessage (WM_QUIT);
				} break;
			default:
				return DefWindowProc (hWnd, uMsg, wParam, lParam);
		}
		return 0;
	}

	//////////////////////////////
	// Window Class Definitions //
	//////////////////////////////

	//Constructors
	Window::Window (void)
	{
	}

	Window::Window (HINSTANCE Instance, LPCWSTR Title, int Width, int Height, BOOL Fullscreen)
	{
		this->InitWindow (Instance, Title, Width, Height, Fullscreen);
	}

	//Destructor
	Window::~Window (void) 
	{
		if (this->WndClassEx != NULL)
			delete this->WndClassEx;
	}

	BOOL Window::InitWindow (HINSTANCE Instance, LPCWSTR Title, int Width, int Height, BOOL Fullscreen)
	{
		this->hInstance = Instance;
		this->WindowTitle = Title;
		this->ScreenWidth = Width;
		this->ScreenHeight = Height;
		this->FullScreen = Fullscreen;
		return this->BuildWindow();
	}

	//Public Methods
	void Window::Show (void)
	{
		ShowWindow (hWnd, SW_SHOWNORMAL);
		UpdateWindow (hWnd);
	}

	BOOL Window::UpdateWindowMsg (void)
	{
		if (PeekMessage (&Msg, NULL, 0, 0, PM_REMOVE))
		{
			if (this->Msg.message == WM_QUIT)
				this->Running = FALSE;
			TranslateMessage (&Msg);
			DispatchMessage (&Msg);
		}
		return Running;
	}

	//Private Methods
	BOOL Window::BuildWindow (void)
	{
		BOOL Success = TRUE;
		Success = this->BuildWndClassEx();
		if (Success)
			Success = this->BuildWndHandle();
		return Success;
	}

	BOOL Window::BuildWndClassEx (void)
	{
		BOOL Success = TRUE;

		this->WndClassEx = new WNDCLASSEX;
		if (this->WndClassEx)
		{
			this->WndClassEx->cbSize		= sizeof (WNDCLASSEX);
			this->WndClassEx->style			= CS_HREDRAW | CS_VREDRAW;
			this->WndClassEx->lpfnWndProc	= WindowProcedure;
			this->WndClassEx->cbClsExtra	= 0;
			this->WndClassEx->cbWndExtra	= 0;
			this->WndClassEx->hInstance		= hInstance;
			this->WndClassEx->hIcon			= LoadIcon (NULL, IDI_APPLICATION);
			this->WndClassEx->hIconSm		= LoadIcon (NULL, IDI_APPLICATION);
			this->WndClassEx->hCursor		= LoadCursor (NULL, IDC_ARROW);
			this->WndClassEx->hbrBackground	= (HBRUSH) GetStockObject (WHITE_BRUSH);
			this->WndClassEx->lpszMenuName	= NULL;
			this->WndClassEx->lpszClassName	= WIN_CLS_NAME;

			if (!RegisterClassEx(this->WndClassEx))
				Success = FALSE;
		}
		else
			Success = FALSE;
		
		return Success;
	}

	BOOL Window::BuildWndHandle (void)
	{
		BOOL Success = TRUE;

		if (this->FullScreen)
		{
			this->hWnd = CreateWindowEx(NULL, WIN_CLS_NAME, WindowTitle, WS_EX_TOPMOST | WS_POPUP,
										0, 0, ScreenWidth, ScreenHeight, NULL, NULL, hInstance, NULL);
		}
		else
		{
			this->hWnd = CreateWindowEx (WS_EX_APPWINDOW | WS_EX_WINDOWEDGE, WIN_CLS_NAME, WindowTitle,
										 WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, ScreenWidth,
										 ScreenHeight, NULL, NULL, hInstance, NULL);
		}
		if (!this->hWnd)
			Success = FALSE;

		return Success;
	}

	//Getters
	HINSTANCE Window::GetWindowInstance (void)
	{
		return this->hInstance;
	}

	HWND Window::GetWindowHandle (void)
	{
		return this->hWnd;
	}

	UINT Window::GetScreenWidth (void)
	{
		return this->ScreenWidth;
	}

	UINT Window::GetScreenHeight (void)
	{
		return this->ScreenHeight;
	}

	BOOL Window::GetFullScreen (void)
	{
		return this->FullScreen;
	}
};